package com.kunminx.core.myUtils.scheduler;

import com.kunminx.core.myUtils.utils.Log;
import io.reactivex.Scheduler;
import io.reactivex.disposables.Disposable;
import io.reactivex.disposables.Disposables;
import io.reactivex.plugins.RxJavaPlugins;
import ohos.eventhandler.EventHandler;

import java.util.concurrent.TimeUnit;

/**
 * HandlerScheduler
 * <p>
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
final class HandlerScheduler extends Scheduler {
    private final EventHandler handler;

    HandlerScheduler(EventHandler eHandler) {
        this.handler = eHandler;
    }

    @Override
    public Disposable scheduleDirect(Runnable run, long delay, TimeUnit unit) {
        if (run == null) {
            throw new NullPointerException("run == null");
        }
        if (unit == null) {
            throw new NullPointerException("unit == null");
        }

        Runnable mRun = run;
        mRun = RxJavaPlugins.onSchedule(run);
        ScheduledRunnable scheduled = new ScheduledRunnable(handler, mRun);
        Log.d("Scheduler=scheduleDirect");
        handler.postTask(scheduled, unit.toMillis(delay));
        return scheduled;
    }

    // private static final int INNER_EVENT_ID = 9819;

    @Override
    public Worker createWorker() {
        return new HandlerWorker(handler);
    }

    private static final class HandlerWorker extends Worker {
        private final EventHandler handler;

        private volatile boolean disposed;

        HandlerWorker(EventHandler eHandler) {
            this.handler = eHandler;
        }

        @Override
        public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
            if (run == null) {
                throw new NullPointerException("run == null");
            }
            if (unit == null) {
                throw new NullPointerException("unit == null");
            }

            Log.d("Scheduler=1");
            if (disposed) {
                return Disposables.disposed();
            }

            Runnable mRun = run;
            mRun = RxJavaPlugins.onSchedule(run);

            ScheduledRunnable scheduled = new ScheduledRunnable(handler, mRun);

            // InnerEvent event1 = InnerEvent.get(InnerEventID, 0, null);

            // Message message = Message.obtain(handler, scheduled);
            // message.obj = this; // Used as token for batch disposal of this worker's runnables.

            Log.d("Scheduler=2=" + unit.toMillis(delay));
            // handler.sendEvent(event1, unit.toMillis(delay));
            //
            handler.postTask(scheduled, unit.toMillis(delay));

            // Re-check disposed state for removing in case we were racing a call to dispose().
            if (disposed) {
                Log.d("Scheduler=3");
                // 不能remove Runnable
                handler.removeAllEvent();
                // handler.removeCallbacks(scheduled);
                return Disposables.disposed();
            }

            return scheduled;
        }

        @Override
        public void dispose() {
            disposed = true;
            Log.d("Scheduler=dispose");

            // 不能remove token
            handler.removeAllEvent();
            // handler.removeCallbacksAndMessages(this /* token */);
        }

        @Override
        public boolean isDisposed() {
            return disposed;
        }
    }

    private static final class ScheduledRunnable implements Runnable, Disposable {
        private final EventHandler handler;
        private final Runnable delegate;

        private volatile boolean disposed;

        ScheduledRunnable(EventHandler eHandler, Runnable rDelegate) {
            this.handler = eHandler;
            this.delegate = rDelegate;
        }

        @Override
        public void run() {
            try {
                Log.d("Scheduler=delegate.run");
                delegate.run();
            } catch (Exception t) {
                RxJavaPlugins.onError(t);
            }
        }

        @Override
        public void dispose() {
            disposed = true;
            Log.d("Scheduler=delegate.dispose");
            // 不能remove Runnable
            handler.removeAllEvent();
            // handler.removeCallbacks(this);
        }

        @Override
        public boolean isDisposed() {
            return disposed;
        }
    }
}